import { HttpService } from '@nestjs/axios';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm';
import * as dayjs from 'dayjs'
import BaseCommemorationDayModelEntity from 'src/entities/base-commemoration-day-model.entity';
import HoroscopeEntity from 'src/entities/horoscope.entity';
import UserCommemorationDayModelEntity from 'src/entities/user-commemoration-day-model.entity';
import UserExtendEntity from 'src/entities/user-extend.entity';
import { computeCommemorationDay, computeSendSmsDate } from 'src/utils/loveDay';
import { EntityManager, In, IsNull, LessThan, Not, Repository } from 'typeorm';

@Injectable()
export class ScheduleService {
  constructor(
    @InjectEntityManager() private entityManager: EntityManager,
    @InjectRepository(HoroscopeEntity)
    private readonly horoscopeEntityRepository: Repository<HoroscopeEntity>,
    @InjectRepository(UserExtendEntity)
    private readonly userExtendEntityRepository: Repository<UserExtendEntity>,
    private readonly httpService: HttpService,
    private readonly configService: ConfigService
  ){}

  async computeCommemorationDayModel(){
    let resData={
      code:0,
      data:{},
      msg:''
    }
    this.entityManager.transaction(async entityManager=>{
      const yesterday=dayjs().add(-1,'day').format('YYYY-MM-DD')
      const today=dayjs().format('YYYY-MM-DD')
      const tomorrow=dayjs().add(1,'day').format('YYYY-MM-DD')

      //#region 先反算基础模板数据
      //1.先将数据同步到model表
      await entityManager.query(`
        INSERT INTO BaseCommemorationDayModel (
          SysID,CommemorationDate,LunarDate,LunarNumDate,SolarDate,IntervalDay,LunarOrSolar,
          Weekly,Circulation,RemindDate,RemindTime,SendSmsIntervalDate,CountDown,UpdateDate
        )
        SELECT B.SysID,B.CommemorationDate,B.LunarDate,B.LunarNumDate,B.SolarDate,B.IntervalDay,B.LunarOrSolar,
        B.Weekly,B.Circulation,B.RemindDate,B.RemindTime,B.SendSmsIntervalDate,B.CountDown,'' UpdateDate
        FROM BaseCommemorationDay B
        WHERE B.Deleted=0 AND NOT EXISTS (
            SELECT 1 FROM BaseCommemorationDayModel BM WHERE BM.SysID=B.SysID
        )
      `)
      //2.取出已过期的数据反算
      const overdueData=await entityManager.find(BaseCommemorationDayModelEntity,{
        select:['SysID','CommemorationDate','LunarOrSolar','Circulation','RemindDate','CountDown'],
        where:({
          CommemorationDate:LessThan(tomorrow),
          CountDown:0
        })
      })
      for(let i=0;i<overdueData.length;i++){
        const item=overdueData[i];
        const newCommemorationDate = computeCommemorationDay(
          item.CommemorationDate,tomorrow,item.Circulation,item.LunarOrSolar,item.CountDown
        )
        const newBaseCommemorationDayModel=new BaseCommemorationDayModelEntity();
        newBaseCommemorationDayModel.CommemorationDate=newCommemorationDate.CommemorationDate;
        newBaseCommemorationDayModel.LunarDate=newCommemorationDate.LunarDate;
        newBaseCommemorationDayModel.LunarNumDate=newCommemorationDate.LunarNumDate;
        newBaseCommemorationDayModel.SolarDate=newCommemorationDate.SolarDate;
        newBaseCommemorationDayModel.IntervalDay=newCommemorationDate.IntervalDay;
        newBaseCommemorationDayModel.Weekly=newCommemorationDate.Weekly;
        newBaseCommemorationDayModel.SendSmsIntervalDate=computeSendSmsDate(newCommemorationDate.CommemorationDate,item.CountDown,item.RemindDate);
        newBaseCommemorationDayModel.UpdateDate=''
        await entityManager.update(BaseCommemorationDayModelEntity,{
          SysID:item.SysID
        },newBaseCommemorationDayModel)
      }
      //3.反算UpdateDate=''跟UpdateDate不是昨天跟今天的IntervalDay
      const emptyUpdateDateData=await entityManager.find(BaseCommemorationDayModelEntity,{
        select:['SysID','CountDown','CommemorationDate'],
        where:([{
          UpdateDate:IsNull()
        },{
          UpdateDate:''
        },{
          UpdateDate:Not(In([today,yesterday]))
        }])
      })
      for(let i=0;i<emptyUpdateDateData.length;i++){
        const item=emptyUpdateDateData[i]
        const newIntervalDay=dayjs(item.CommemorationDate).diff(tomorrow, 'day');
        await entityManager.update(BaseCommemorationDayModelEntity,{
          SysID:item.SysID
        },{
          IntervalDay:newIntervalDay,
          UpdateDate:today
        })
      }
      //4.反算UpdateDate是昨天的IntervalDay
      await entityManager.query(`
        UPDATE BaseCommemorationDayModel
        SET IntervalDay=(IFNULL(IntervalDay,0)-1),UpdateDate='${today}'
        WHERE UpdateDate='${yesterday}'
      `)
      //#endregion

      //#region 反算用户纪念日表
      //1.先将数据同步到model表
      await entityManager.query(`
        INSERT INTO UserCommemorationDayModel (
          SysID,BaseSysID,BaseCommemorationDate,CommemorationDate,LunarDate,LunarNumDate,SolarDate,IntervalDay,LunarOrSolar,
          Weekly,Circulation,RemindDate,RemindTime,Edited,SendSmsIntervalDate,CountDown,UpdateDate
        )
        SELECT U.SysID,U.BaseSysID,U.BaseCommemorationDate,U.CommemorationDate,U.LunarDate,U.LunarNumDate,U.SolarDate,U.IntervalDay,
          U.LunarOrSolar,U.Weekly,U.Circulation,U.RemindDate,U.RemindTime,U.Edited,U.SendSmsIntervalDate,U.CountDown,'' UpdateDate
        FROM UserCommemorationDay U
        WHERE U.Deleted=0 AND NOT EXISTS (
            SELECT 1 FROM UserCommemorationDayModel UM WHERE U.SysID=UM.SysID
        )
      `)
      //2.将base表中的数据直接更新到user表避免重复计算
      await entityManager.query(`
        UPDATE UserCommemorationDayModel UC,BaseCommemorationDayModel BC 
        SET UC.CommemorationDate=BC.CommemorationDate,UC.LunarDate=BC.LunarDate,UC.LunarNumDate=BC.LunarNumDate,UC.SolarDate=BC.SolarDate,
          UC.IntervalDay=BC.IntervalDay,UC.Weekly=BC.Weekly,UC.SendSmsIntervalDate=BC.SendSmsIntervalDate,UC.UpdateDate=BC.UpdateDate
        WHERE UC.BaseSysID=BC.SysID AND UC.BaseSysID!='-1'
      `)
      //3.取出已过期的数据反算
      const overdueUserData=await entityManager.find(UserCommemorationDayModelEntity,{
        select:['SysID','CommemorationDate','LunarOrSolar','Circulation','RemindDate','CountDown'],
        where:({
          CommemorationDate:LessThan(tomorrow),
          CountDown:0
        })
      })
      for(let i=0;i<overdueUserData.length;i++){
        const item=overdueUserData[i]
        const newCommemorationDate = computeCommemorationDay(
          item.CommemorationDate,tomorrow,item.Circulation,item.LunarOrSolar,item.CountDown
        )
        const newBaseCommemorationDayModel=new UserCommemorationDayModelEntity();
        newBaseCommemorationDayModel.CommemorationDate=newCommemorationDate.CommemorationDate;
        newBaseCommemorationDayModel.LunarDate=newCommemorationDate.LunarDate;
        newBaseCommemorationDayModel.LunarNumDate=newCommemorationDate.LunarNumDate;
        newBaseCommemorationDayModel.SolarDate=newCommemorationDate.SolarDate;
        newBaseCommemorationDayModel.IntervalDay=newCommemorationDate.IntervalDay;
        newBaseCommemorationDayModel.Weekly=newCommemorationDate.Weekly;
        newBaseCommemorationDayModel.SendSmsIntervalDate=computeSendSmsDate(newCommemorationDate.CommemorationDate,item.CountDown,item.RemindDate);
        newBaseCommemorationDayModel.UpdateDate=''
        await entityManager.update(UserCommemorationDayModelEntity,{
          SysID:item.SysID
        },newBaseCommemorationDayModel)
      }
      //4.反算UpdateDate=''跟UpdateDate不是昨天跟今天的IntervalDay
      const emptyUpdateDateUserData=await entityManager.find(UserCommemorationDayModelEntity,{
        select:['SysID','CountDown','CommemorationDate'],
        where:([{
          UpdateDate:IsNull()
        },{
          UpdateDate:''
        },{
          UpdateDate:Not(In([today,yesterday]))
        }])
      })
      for(let i=0;i<emptyUpdateDateUserData.length;i++){
        const item=emptyUpdateDateUserData[i]
        const newIntervalDay=dayjs(item.CommemorationDate).diff(tomorrow, 'day');
        await entityManager.update(UserCommemorationDayModelEntity,{
          SysID:item.SysID
        },{
          IntervalDay:newIntervalDay,
          UpdateDate:today
        })
      }
      //5.反算UpdateDate是昨天的IntervalDay
      await entityManager.query(`
        UPDATE UserCommemorationDayModel
        SET IntervalDay=(IFNULL(IntervalDay,0)-1),UpdateDate='${today}'
        WHERE UpdateDate='${yesterday}'
      `)
      //#endregion

    })
      .then(()=>{
        resData={
          code:0,
          data:{},
          msg:'反算数据成功!'
        }
      })
      .catch((e)=>{
        resData={
          code:500,
          data:{
            e
          },
          msg:'反算数据失败!'
        }
      })
    return resData
  }

  async syncCommemorationDayData(){
    let resData={
      code:0,
      data:{},
      msg:''
    }
    await this.entityManager.transaction(async entityManager=>{
      await entityManager.query(`
        UPDATE BaseCommemorationDay BC,BaseCommemorationDayModel BCM 
        SET BC.CommemorationDate=BCM.CommemorationDate,BC.LunarDate=BCM.LunarDate,BC.LunarNumDate=BCM.LunarNumDate,BC.SolarDate=BCM.SolarDate,
          BC.IntervalDay=BCM.IntervalDay,BC.Weekly=BCM.Weekly,BC.SendSmsIntervalDate=BCM.SendSmsIntervalDate,BC.UpdateDate=BCM.UpdateDate
        WHERE BC.SysID=BCM.SysID AND BC.Deleted=0;
      `)
      await entityManager.query(`
        UPDATE UserCommemorationDay UC,UserCommemorationDayModel UCM 
        SET UC.CommemorationDate=UCM.CommemorationDate,UC.LunarDate=UCM.LunarDate,UC.LunarNumDate=UCM.LunarNumDate,UC.SolarDate=UCM.SolarDate,
          UC.IntervalDay=UCM.IntervalDay,UC.Weekly=UCM.Weekly,UC.SendSmsIntervalDate=UCM.SendSmsIntervalDate,UC.UpdateDate=UCM.UpdateDate
        WHERE UC.SysID=UCM.SysID AND UC.Deleted=0;
      `)
    })
      .then(()=>{
        resData={
          code:0,
          data:{},
          msg:'同步数据成功!'
        }
      })
      .catch((e)=>{
        resData={
          code:500,
          data:{
            e
          },
          msg:'同步数据失败!'
        }
      })
    return resData
  }

  async getNetworkData(){
    let resData={
      code:0,
      data:{},
      msg:''
    }

    //#region 获取星座运势数据
    const JuheUrl=this.configService.get('JUHECN_CONFIG').url;
    const JuheKey=this.configService.get('JUHECN_CONFIG').key;
    const horoscope = [
      '白羊座',
      '金牛座',
      '双子座',
      '巨蟹座',
      '狮子座',
      '处女座',
      '天秤座',
      '天蝎座',
      '射手座',
      '摩羯座',
      '双鱼座',
      '水瓶座',
    ];
    for(let i=0;i<horoscope.length;i++){
      const consName=encodeURI(horoscope[i])
      const url= `${JuheUrl}/constellation/getAll?consName=${consName}&type=week&key=${JuheKey}`
      await this.httpService.axiosRef.get(url)
        .then(async ({data})=>{
          const { resultcode, name, date, health, love, money, work } = data;
          if(resultcode==200){
            const horoscopeEntity=new HoroscopeEntity();
            horoscopeEntity.Date=date;
            horoscopeEntity.Health=health;
            horoscopeEntity.Love=love;
            horoscopeEntity.Money=money;
            horoscopeEntity.Work=work;
            horoscopeEntity.UpdateTime=dayjs().format('YYYY-MM-DD HH:mm:ss')
            await this.horoscopeEntityRepository.update({
              Name:name
            },horoscopeEntity)
          }
        })
    }
    //#endregion
    
    resData={
      code:200,
      data:{},
      msg:'获取星座运势成功!'
    }
    
    return resData
  }

  async resetActionData(){
    let resData={
      code:200,
      data:{},
      msg:''
    }
    const now=dayjs().format('YYYY-MM-DD HH:mm:ss')
    const today=dayjs().format('YYYY-MM-DD');
    const yesterday=dayjs().add(-1, "day").format("YYYY-MM-DD");
    //#region 重置打卡数据
    await this.entityManager.transaction(async entityManager=>{
      const resetSignUserExtend=new UserExtendEntity()
      resetSignUserExtend.IsSign=0;
      resetSignUserExtend.UpdateTime=now;
      await entityManager.update(UserExtendEntity,{},resetSignUserExtend)
      await entityManager.query(`
        UPDATE UserExtend SET ContinueSign=0,UpdateTime='${now}' WHERE UserSysID NOT IN (
          SELECT UserSysID FROM UserSignData WHERE SignDate='${today}' OR SignDate='${yesterday}'
        )
      `)
    })
    .then(()=>{
      resData={
        code:0,
        data:{},
        msg:'重置数据成功!'
      }
    })
    .catch((e)=>{
      resData={
        code:500,
        data:{
          e
        },
        msg:'重置数据失败!'
      }
    })
    //#endregion
    return resData
  }
}
